package pageesdto

import (
	"context"
	"gitee.com/ichub/webcli/common/base/baseconfig"
	"gitee.com/ichub/webcli/common/base/basedto"
	"gitee.com/ichub/webcli/common/base/baseutils/jsonutils"
	"gitee.com/ichub/webcli/common/base/pagedto"
	"gitee.com/ichub/webcli/common/base/pagedto/pagebase"
	"gitee.com/ichub/webcli/common/ichubcontext"
	"gitee.com/ichub/webcli/common/ichubelastic"
	"github.com/olivere/elastic"
	"github.com/sirupsen/logrus"
)

/*
	@Title    文件名称: pageesrequest.go
	@Description  描述:  es请求消息

	@Author  作者: leijianming@163.com  时间(2024-02-22 22:38:21)
	@Update  作者: leijianming@163.com  时间(2024-02-21 22:38:21)
*/

/*
索是 ES 最为复杂精妙的地方，这里只示例项目中较为常用的查询。

	ES 中的查询分为三大类，

一是 Term-level queries（我翻译成字段匹配），
二是 Full-text queries（全文搜索）
，三是不常用的 Specialized queries（专门查询）。各自可细分为如下几种：

	Term-level queries
	exists query 字段是否存在值
	fuzzy query 模糊查询
	ids query ID 查询
	prefix query 前缀查询
	range query 范围查询
	regexp query 正则查询
	term query 精确匹配单个字段
	terms query 精确匹配单个字段，但使用多值进行匹配，类似于 SQL 中的 in 操作
	terms_set query 字段集合查询。文档需包含字段集合中指定的最少数量字段
	wildcard query 通配符查询
	Full-text queries
	match query 单字段搜索（匹配分词结果，不需要全文匹配）
	Specialized queries
	script query 脚本查询

原文链接：https://blog.csdn.net/K346K346/article/details/120906440
*/
const (
	AggSign_COUNT = "count"
	AggSign_MAX   = "max"
	AggSign_MIN   = "min"
	AggSign_AVG   = "avg"
	AggSign_SUM   = "sum"
	AggSign_STATS = "stats"
)

type IchubPageEsRequest struct {
	pagedto.IchubPageRequest
	//ES INDEX名称
	IndexName string                    `json:"index_name"`
	AggFields *pagebase.IchubQueryField `json:"agg_fields,omitempty"`

	EsClient *ichubelastic.ElasticClient `json:"-"`
}

func New() *IchubPageEsRequest {

	var req = &IchubPageEsRequest{}
	req.EsClient = ichubcontext.IchubClient.IniEsClient().Esclient()
	req.InitPage()
	req.InitProxy(req)
	req.IchubPageRequest.InitProxy(req.IchubPageRequest)
	return req
}

func NewIchubPageEsRequest() *IchubPageEsRequest {

	return New()
}
func NewEsRequest(pageSize, current int) *IchubPageEsRequest {
	var page = New()
	page.PageCurrent = current
	page.PageSize = pageSize

	return page
}
func NewPageEsRequest(indexName string) *IchubPageEsRequest {
	var page = New()
	page.IndexName = indexName

	return page
}

func (this *IchubPageEsRequest) Clear() {
	this.IchubPageRequest.Clear()
	this.AggFields = nil
}

func (this *IchubPageEsRequest) IniDefault() {

	var clientDto = baseconfig.NewElasticClientDto()
	clientDto.URL = "http://192.168.14.58:9200"
	clientDto.Username = "elastic"
	clientDto.Password = "123456"
	this.Ini(clientDto)

}
func (this *IchubPageEsRequest) ValueOfPageRequest(that *IchubPageEsRequest) *IchubPageEsRequest {

	this.IchubPageRequest = that.IchubPageRequest
	this.IndexName = that.IndexName
	this.AggFields = that.AggFields
	this.IchubPageRequest.InitProxy(this.IchubPageRequest)
	return this

}
func (this *IchubPageEsRequest) Ini(clientDto *baseconfig.ElasticClientDto) {

	this.EsClient.ClientDto = clientDto

}

func (this *IchubPageEsRequest) Open() {
	if this.EsClient.ClientDto == nil {
		this.IniDefault()
	}
	this.EsClient.Open()
}

func (this *IchubPageEsRequest) esOrderBy(searchService *elastic.SearchService) *elastic.SearchService {
	for _, v := range this.OrderBys {
		searchService.Sort(v.Field, v.Sort == "asc")

	}
	return searchService

}
func (this *IchubPageEsRequest) EsQueryResult(attachResp bool) (*IchubPageEsResult, error) {
	var result = NewIchubPageEsResult()

	searchResult, err := this.EsQuery()

	if err != nil {
		logrus.Error(err)
		return result.FailMsg(err.Error()), err

	}
	result.ValueOf(this, searchResult)
	if !attachResp {
		result.SearchResult = nil
	}

	logrus.Info(result)
	return result, err
}
func (this *IchubPageEsRequest) EsFuzzy(field string, opValue interface{}) *IchubPageEsRequest {

	this.IchubPageRequest.QueryFields(field, pagebase.EsFuzzy, []interface{}{opValue})
	return this
}
func (this *IchubPageEsRequest) EsTerm(field string, opValue interface{}) *IchubPageEsRequest {

	this.IchubPageRequest.QueryFields(field, pagebase.EsTerm, []interface{}{opValue})
	return this
}
func (this *IchubPageEsRequest) Stats(field string) *IchubPageEsRequest {
	this.AggFields.Field = field
	this.AggFields.OpType = AggSign_STATS

	return this
}
func (this *IchubPageEsRequest) Avg(field string) *IchubPageEsRequest {
	this.AggFields.Field = field
	this.AggFields.OpType = AggSign_AVG

	return this
}
func (this *IchubPageEsRequest) Max(field string) *IchubPageEsRequest {
	this.AggFields.Field = field
	this.AggFields.OpType = AggSign_MAX

	return this
}
func (this *IchubPageEsRequest) Min(field string) *IchubPageEsRequest {
	this.AggFields.Field = field
	this.AggFields.OpType = AggSign_MIN

	return this
}
func (this *IchubPageEsRequest) Sum(field string) *IchubPageEsRequest {
	this.AggFields.Field = field
	this.AggFields.OpType = AggSign_SUM

	return this
}
func (this *IchubPageEsRequest) Count(field string) *IchubPageEsRequest {
	this.AggFields.Field = field
	this.AggFields.OpType = AggSign_COUNT

	return this
}

// 排序字段是keyword
func (this *IchubPageEsRequest) EsCount() (int64, error) {

	logrus.Info(this.ToPrettyString())
	countService := this.EsClient.Client().Count(this.IndexName)
	var query = NewEsQueryService(this).BuildQuery()
	//	this.esOrderBy(countService)
	if query != nil {
		countService.Query(query)
	}
	count, err := countService.Do(context.Background())

	if err != nil {
		logrus.Error(err)
	}
	logrus.Info(count)
	return count, err
}
func (this *IchubPageEsRequest) EsQuery() (*elastic.SearchResult, error) {
	if len(this.IndexName) == 0 {
		return nil, basedto.NewIchubError(500, "index name is empty!")
	}
	logrus.Info(this.ToPrettyString())
	searchService := this.EsClient.Client().Search().
		Index(this.IndexName). // 设置索引名
		//	Query(this.MatchQuery()). // 设置查询条件
		//	Sort("Created", true).    // 设置排序字段，根据Created字段升序排序，第二个参数false表示逆序
		From(this.Start()). // 设置分页参数 - 起始偏移量，从第0行记录开始
		Size(this.Limit()). // 设置分页参数 - 每页大小
		Pretty(true)        // 查询结果返回可读性较好的JSON格式
	var query = NewEsQueryService(this).BuildQuery()
	if query != nil {
		searchService.Query(query)
	}
	//	NewEsQueryService(this).Query(searchService)
	this.esOrderBy(searchService)

	searchResult, err := searchService.Do(context.Background())

	if err != nil {
		logrus.Error(err)
	}
	logrus.Info(jsonutils.ToJsonPretty(searchResult))
	return searchResult, err
}

func (this *IchubPageEsRequest) EsFindBy(id string) (*elastic.GetResult, error) {
	//	this.Open()
	result, err := this.EsClient.Client().Get().
		Index("weibo").Id(id).
		Do(context.Background())
	if err != nil {
		logrus.Error(err)
		return nil, err
	}
	logrus.Info(jsonutils.ToJsonPretty(result))
	return result, err
}

func (this *IchubPageEsRequest) esDropIndex(indexName string) {
	this.client().DeleteIndex(indexName)
}

// EsCreateIndex
// esDropIndex
func (this *IchubPageEsRequest) EsCreateIndex(indexName string, mapping string) (bool, error) {
	this.IndexName = indexName

	client := this.EsClient.Client()
	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()
	// 首先检测下weibo索引是否存在
	exists, err := client.IndexExists(indexName).Do(ctx)

	if err != nil {
		logrus.Error(err)
		return false, err
	}
	if !exists {
		// weibo索引不存在，则创建一个
		r, err := client.CreateIndex(indexName).BodyString(mapping).Do(ctx)
		if err != nil {
			logrus.Error(err)
			return false, err
		}
		logrus.Info(r)
	}
	return true, err

}
func (this *IchubPageEsRequest) client() *elastic.Client {
	return this.EsClient.Client()
}

func (this *IchubPageEsRequest) esSaveIndex(id string, model interface{}) (*elastic.IndexResponse, error) {

	client := this.EsClient.Client()

	// 使用client创建一个新的文档
	indexRep, err := client.Index().
		Index(this.IndexName).   // 设置索引名称
		Id(id).                  // 设置文档id
		BodyJson(model).         // 指定前面声明的微博内容
		Do(context.Background()) // 执行请求，需要传入一个上下文对象
	if err != nil {
		logrus.Error(err)
	}
	logrus.Printf("文档Id %s, 索引名 %s\n", indexRep.Id, indexRep.Index)
	return indexRep, err
}

func (this *IchubPageEsRequest) EsDeleteIndex(id string) (*elastic.DeleteResponse, error) {
	var ctx = context.Background()
	r, err := this.client().Delete().
		Index(this.IndexName).Id(id).Refresh("true").Do(ctx)
	if err != nil {
		logrus.Error(err)
	}
	return r, err
}
func (this *IchubPageEsRequest) EsGetMapping(indexName string) (map[string]interface{}, error) {
	return this.client().GetMapping().Index(indexName).Type().Do(context.Background())

}
